package kr.co.redcircle.console.helper;

import java.io.IOException;
import java.util.List;

import kr.co.redcircle.console.dialog.ConsoleDialog;
import kr.co.redcircle.console.service.ConsoleRegistry;
import kr.co.redcircle.console.service.RegKey;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.wb.swt.SWTResourceManager;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

public class ObjectTree {

	private static final String CLASS = "class";
	private static final String EVENT = "event";
	private static final String SEPARATOR = "SEPARATOR";
	private static final String NORMAL = "NORMAL";
	private static final String CHECK = "CHECK";
	private static final String RADIO = "RADIO";
	private static final String TYPE = "type";
	private static final String XPATH_MENU = "//menu";
	private static final String SYSTEM_WORKER = "system.worker";
	private static final String SYSTEM_MONITOR = "system.monitor";
	private static final String SYSTEM_NAME = "system.name";
	private static final String NODE = "node";
	private static final String MENU = "menu";
	private static final String ICON = "icon";
	private static final String TEXT = "text";
	private static final String COLLECTION_NODE = "//collection/node";
	private static final String COLLECTION_TYPE_OBJECT_TREE = "//collection[@type='objectTree']";
	private static final String ID = "id";
	private static final String ITEM = "item";
	private static final String ENABLE_MENU = "ENABLE_MENU";
	private static final String CONSOLE_CONFIG_XML = "/kr/co/redcircle/console/config/consoleConfig.xml";
	private static SAXBuilder builder = new SAXBuilder();
    private static Document document = null;

    static{
		try {
			document = builder.build(ConsoleDialog.class.getResourceAsStream(CONSOLE_CONFIG_XML));
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }

    @SuppressWarnings("unchecked")
	public static Tree build(Composite composite, FormData layoutData) {
    	
    	Tree tree = new Tree(composite, SWT.BORDER);
    	final Menu menu = new Menu(tree);
    	tree.setMenu(menu);
		tree.setLayoutData(layoutData);
    	
		
		MenuListener listener = new MenuListener() {
			
			@Override
			public void menuShown(MenuEvent e) {
				for (MenuItem item : menu.getItems()){
					item.setEnabled(false);
				}

				Tree tgrTree = (Tree)ConsoleRegistry.getInstance().get(RegKey.BROKER_OBJECT_TREE);
				TreeItem[] treeItemArray = tgrTree.getSelection();
				if (treeItemArray.length > 0){
					Object itemData = treeItemArray[0].getData(ENABLE_MENU);
					if (itemData != null){
						Element menuElement = (Element)itemData;
						List<Element> menuList = menuElement.getChildren(ITEM);
						
						for (Element menuTmpElement : menuList){
							String menuIdString = menuTmpElement.getAttributeValue(ID);
							Object dataObj = menu.getData(menuIdString);
							if (dataObj != null){
								((MenuItem)dataObj).setEnabled(true);
							}
						}
					}
				}
				
				System.out.println("MenuListener.menuShown");
			}

			@Override
			public void menuHidden(MenuEvent e) {}

		};
		
		menu.addMenuListener(listener);
		
		
		Object searchResult = null;
		
		try {
			searchResult = XPath.selectSingleNode(document, COLLECTION_TYPE_OBJECT_TREE);
		} catch (JDOMException e) {
			e.printStackTrace();
		}

		if (searchResult != null){
			
			buildPopupMenus(menu, (Element)searchResult);
			buildTreeItem(tree, (Element)searchResult);
			
		}
		
		return tree;
    }

	@SuppressWarnings("unchecked")
	private static void buildTreeItem(Tree tree, Element searchResult) {
		
		List<Element> treeNodeList = null;
		
		try {
			
			treeNodeList = (List<Element>) XPath.selectNodes(searchResult, COLLECTION_NODE);
			
			if (treeNodeList != null){
				
				for (Element rootNodeElement : treeNodeList){
					
					String textString = rootNodeElement.getAttributeValue(TEXT);
					String iconString = rootNodeElement.getAttributeValue(ICON);
					
					TreeItem rootTreeItem = new TreeItem(tree, SWT.NONE);
					rootTreeItem.setImage(SWTResourceManager.getImage(ObjectTree.class, iconString));
					rootTreeItem.setText(textString);
					
					rootTreeItem.setData(ENABLE_MENU, rootNodeElement.getChild(MENU));
					
					List<Element> menuChild = (List<Element>)rootNodeElement.getChildren(NODE);			
					
					for (Element tgrElement : menuChild){
						buildChildTree(rootTreeItem, tgrElement);
					}
					
				}
			}
			
		} catch (JDOMException e) {
			e.printStackTrace();
		}
	}


	@SuppressWarnings("unchecked")
	private static void buildChildTree(TreeItem childItem, Element childElement) {

		String textString = childElement.getAttributeValue(TEXT);
		String iconString = childElement.getAttributeValue(ICON);
		
		TreeItem tmpTreeItem = new TreeItem(childItem, SWT.NONE);
		tmpTreeItem.setImage(SWTResourceManager.getImage(ObjectTree.class, iconString));
		tmpTreeItem.setText(textString);
		tmpTreeItem.setData(ENABLE_MENU, childElement.getChild(MENU));
		
		if (textString.equals(SYSTEM_NAME)){
			ConsoleRegistry.getInstance().put(RegKey.SYSTEM_NAME_NODE, tmpTreeItem);
		}else if (textString.equals(SYSTEM_MONITOR)){
			ConsoleRegistry.getInstance().put(RegKey.SYSTEM_MONITOR_NODE, tmpTreeItem);
		}else if (textString.equals(SYSTEM_WORKER)){
			ConsoleRegistry.getInstance().put(RegKey.SYSTEM_WORKER_NODE, tmpTreeItem);
		}
		
		List<Element> childList = childElement.getChildren(NODE);
		if (childList.size() > 0){
			
			for (Element inChildElement : childList){
				
				buildChildTree(tmpTreeItem,  inChildElement);
				
			}
		}
				
	}

	@SuppressWarnings("unchecked")
	private static void buildPopupMenus(Menu menu, Element searchResult) {
		
		Element menuNode = null;
		
		try {
			
			menuNode = (Element) XPath.selectSingleNode(searchResult, XPATH_MENU);
			if (menuNode != null){
				List<Element> menuchild = (List<Element>)menuNode.getChildren();			
	
				for (Element tgrElement : menuchild){
					buildMenuItem(tgrElement, menu);
				}
			}
			
			
		} catch (JDOMException e) {
			e.printStackTrace();
		}
		
	}

	@SuppressWarnings("unchecked")
	private static MenuItem buildMenuItem(Element tgrElement, Menu menu) {
		
		MenuItem tmpItem = null;

		String idString = tgrElement.getAttributeValue(ID);
		String typeString = tgrElement.getAttributeValue(TYPE);
		
		if (typeString.equals(RADIO)){
			tmpItem = new MenuItem(menu, SWT.RADIO);
			String textString = tgrElement.getAttributeValue(TEXT);
			String iconString = tgrElement.getAttributeValue(ICON);
			tmpItem.setImage(SWTResourceManager.getImage(ObjectTree.class, iconString));
			tmpItem.setText(textString);
			menu.setData(idString, tmpItem);
			
		}else if (typeString.equals(CHECK)){
			tmpItem = new MenuItem(menu, SWT.CHECK);
			String textString = tgrElement.getAttributeValue(TEXT);
			String iconString = tgrElement.getAttributeValue(ICON);
			tmpItem.setImage(SWTResourceManager.getImage(ObjectTree.class, iconString));
			tmpItem.setText(textString);
			
		}else if (typeString.equals(NORMAL)){
			tmpItem = new MenuItem(menu, SWT.NONE);
			String textString = tgrElement.getAttributeValue(TEXT);
			String iconString = tgrElement.getAttributeValue(ICON);
			tmpItem.setImage(SWTResourceManager.getImage(ObjectTree.class, iconString));
			tmpItem.setText(textString);
			
		}else if (typeString.equals(SEPARATOR)){
			tmpItem = new MenuItem(menu, SWT.SEPARATOR);
			
		}
		
		if (tmpItem != null){
			//tmpItem.setEnabled(false);
			menu.setData(idString, tmpItem);
			System.out.println("adding menu item : " + idString);
			List<Element> itemEvent = tgrElement.getChildren(EVENT);		
			buildItemEvent(tmpItem, itemEvent);
		}
		
		return tmpItem;
		
	}

	private static void buildItemEvent(MenuItem tmpItem, List<Element> itemEvent) {
		
		for (Element eventElement : itemEvent){
			
			String typeString = eventElement.getAttributeValue(TYPE);
			String classString = eventElement.getAttributeValue(CLASS);
			
			try {
				
				Class<?> eventClass = Class.forName(classString);
				eventApply(typeString, tmpItem, eventClass.newInstance());
				
			} catch (ClassNotFoundException e) {
				e.printStackTrace();				
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}

	private static void eventApply(String typeString, MenuItem tmpItem, Object eventObject) {

		if (eventObject != null){
			int eventMode = (Integer) SWTConstantHelper.get(typeString);
			switch(eventMode){
			case SWT.Selection : 
				tmpItem.addSelectionListener((SelectionListener) eventObject);
				break;
	
			}
		}
	}

}
